package com.ruan.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruan.common.Code;
import com.ruan.common.Result;
import com.ruan.exception.BusinessException;
import com.ruan.mapper.*;
import com.ruan.pojo.*;
import com.ruan.pojoExt.BusinessTripExt;
import com.ruan.service.BusinessTripService;
import com.ruan.service.DepartmentService;
import com.ruan.service.EmployeeService;
import com.ruan.utils.DateUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.sql.Date;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;
import java.util.stream.Collectors;

@Service
@Slf4j
@Transactional
public class BusinessTripServiceImpl extends ServiceImpl<BusinessTripMapper, BusinessTrip> implements BusinessTripService {

    private static ThreadLocal<Long> threadLocal = new ThreadLocal<>();

    @Resource
    private BusinessTripMapper businessTripMapper;

    @Autowired
    private DepartmentService departmentService;

    @Resource
    private OnDutyMapper onDutyMapper;

    @Resource
    private AdminMapper adminMapper;

    @Resource
    private EmployeeLeaveMapper employeeLeaveMapper;

    @Autowired
    private EmployeeMapper employeeMapper;

    @Autowired
    private EmployeeService employeeService;


//    /**
//     * 分页和条件查询全部在职员工的出差信息
//     * @param currentPage 当前页
//     * @param pageSize 每页最大数
//     * @param LTOQueryCondition 查询条件：封装了月份和手机号字段
//     * @return
//     */
//    @Override
//    public IPage<BusinessTrip> selectByPageAndCondition(int currentPage,
//                                                        int pageSize,
//                                                        LTOQueryCondition LTOQueryCondition) {
//        System.out.println("BusinessTrip--pageSize::::"+pageSize);
//        Date month = LTOQueryCondition.getMonth();//2023-2-1
//        IPage<BusinessTrip> iPage=new Page<>(currentPage,pageSize);
//        QueryWrapper<BusinessTrip> queryWrapper = new QueryWrapper<>();
//        queryWrapper.like(LTOQueryCondition.getName()!=null,"name", LTOQueryCondition.getName());
//        queryWrapper.eq(LTOQueryCondition.getDepartmentId()!=null,"department", LTOQueryCondition.getDepartmentId());
//        queryWrapper.like("status","同意");
//        queryWrapper.select("*","COUNT(phone) AS count").groupBy("phone");
//
//        if (month!=null){
//            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-01");
//            String firstDay = sdf.format(month);//每月的第一天
//            String lastDay = DateUtils.getLastDay(firstDay);//每月最后一天
//
//            queryWrapper.between("leave_time",firstDay,lastDay);
//
//            return businessTripMapper.selectPage(iPage,queryWrapper);
//        }else {
//
//            return businessTripMapper.selectPage(iPage,queryWrapper);
//        }
//    }

    /**
     * 根据日期和手机号查询单个在职员工的出差详细记录
     * @param ltoDetailCondition 查询条件：封装了月份和手机号字段
     * @return
     */
    @Override
    public List<BusinessTripExt> selectLeaveDetailByPhoneAndDate(LTODetailCondition ltoDetailCondition) {
        System.out.println("selectLeaveDetailByPhoneAndDate的参数是："+ltoDetailCondition);
        String phone = ltoDetailCondition.getPhone();//手机号
        Date month = ltoDetailCondition.getMonth();//2024-2-1


        QueryWrapper<BusinessTrip> queryWrapper = new QueryWrapper<>();
        queryWrapper.like("status","同意");
        QueryWrapper<Employee> employeeQueryWrapper = new QueryWrapper<>();
        employeeQueryWrapper.eq("phone",phone);
        Employee employee = employeeMapper.selectOne(employeeQueryWrapper);

        queryWrapper.eq("employee_id",employee.getId());
        if (month!=null){

            String firstDay = month.toString();//2023-3-1
            String lastDay = DateUtils.getLastDay(firstDay);//2023-3-31
            queryWrapper.between("leave_time",firstDay,lastDay);

            List<BusinessTrip> businessTripList = businessTripMapper.selectList(queryWrapper);

//            List<BusinessTripExt> businessTripExtList = (List<BusinessTripExt>) new BusinessTripExt();
            List<BusinessTripExt> businessTripExtList = new ArrayList<>();

            for (BusinessTrip businessTrip : businessTripList) {
            // 在这里处理每个对象
            BusinessTripExt businessTripExt = new BusinessTripExt();
            BeanUtils.copyProperties(businessTrip, businessTripExt);
            Employee employee1 = employeeService.getById(businessTrip.getEmployeeId());
            Department department = departmentService.getById(businessTrip.getDepartmentId());
            businessTripExt.setEmployeeName(employee1.getName());
            businessTripExt.setDepartmentName(department.getName());
            //把有departmentName的一个个businessTripExt存入businessTripExtList里
            businessTripExtList.add(businessTripExt);
        }
        System.out.println("month!=null的businessTripExtList改造完成了吗"+businessTripExtList);
        return businessTripExtList;
//      return businessTripMapper.selectList(queryWrapper);
        }else {
            List<BusinessTrip> businessTripList = businessTripMapper.selectList(queryWrapper);
            System.out.println("businessTripList改造前：" + businessTripList);
            List<BusinessTripExt> businessTripExtList = new ArrayList<>();
            //new BusinessTripExt();ArrayList<>()

//            System.out.println("businessTripList改造后：" + businessTripExtList);

            for (BusinessTrip businessTrip : businessTripList) {
                BusinessTripExt businessTripExt = new BusinessTripExt();
// 复制 BusinessTrip 对象的属性到 BusinessTripExt 对象中
                //先把所有原属性搬过去，再拓展没有的属性//属性迁移
                //可以试试BeanUtils.copyProperties(businessTrip, businessTripExt);
                businessTripExt.setId(businessTrip.getId());
                businessTripExt.setEmployeeId(businessTrip.getEmployeeId());
//                businessTripExt.setName(businessTrip.getName());
//                businessTripExt.setPosition(businessTrip.getPosition());
//                businessTripExt.setPhone(businessTrip.getPhone());
                businessTripExt.setDepartmentId(businessTrip.getDepartmentId());

                businessTripExt.setPlace(businessTrip.getPlace());
                businessTripExt.setReason(businessTrip.getReason());
                businessTripExt.setLeaveTime(businessTrip.getLeaveTime());
                businessTripExt.setBackTime(businessTrip.getBackTime());
                businessTripExt.setDay(businessTrip.getDay());
                businessTripExt.setType(businessTrip.getType());
                businessTripExt.setBudget(businessTrip.getBudget());
                businessTripExt.setActualCost(businessTrip.getActualCost());
                businessTripExt.setSubmitTime(businessTrip.getSubmitTime());
                businessTripExt.setStatus(businessTrip.getStatus());
                businessTripExt.setApprover(businessTrip.getApprover());
                businessTripExt.setCount(businessTrip.getCount());

                // 在这里处理每个对象

                Employee employee1 = employeeService.getById(businessTrip.getEmployeeId());
                Department department = departmentService.getById(businessTrip.getDepartmentId());

                businessTripExt.setEmployeeName(employee1.getName());
                businessTripExt.setDepartmentName(department.getName());
                //把有departmentName的一个个businessTripExt存入businessTripExtList里
                businessTripExtList.add(businessTripExt);
            }
            System.out.println("businessTripExtList改造完成了吧:"+businessTripExtList);
            return businessTripExtList;
//            return businessTripMapper.selectList(queryWrapper);
        }
    }


    /**
     * 同意出差申请
     * @param id 员工id
     * @param adminId 管理员id
     */
    @Override
    public void agreed(Integer id,Integer adminId) {
        BusinessTrip businessTrip = businessTripMapper.selectById(id);
        businessTrip.setStatus("同意");
        Admin admin = adminMapper.selectById(adminId);
        businessTrip.setApprover(admin.getUsername());
        businessTripMapper.updateById(businessTrip);

        Date startTime = businessTrip.getLeaveTime();
        Date endTime = businessTrip.getBackTime();
        Long employeeId = businessTrip.getEmployeeId();
//        String phone = businessTrip.getPhone();
        Integer leaveDay = businessTrip.getDay();

        if (startTime.equals(endTime)){
            OnDuty onDuty = new OnDuty();
            onDuty.setEmployeeId(businessTrip.getEmployeeId());
//            onDuty.setName(businessTrip.getName());
//            onDuty.setPhone(phone);
            onDuty.setDepartmentId(businessTrip.getDepartmentId());
//            onDuty.setDepartment(businessTrip.getDepartment());
//            onDuty.setPosition(businessTrip.getPosition());
            onDuty.setStatus("出差");
            onDuty.setDay(startTime);
            onDutyMapper.insert(onDuty);
        }else {
            //4-20 4-21 4-22
            Calendar calendar =Calendar.getInstance();
            calendar.setTime(startTime);
            List<Date> dateList = new ArrayList<>();
            dateList.add(startTime);
            for (int i = 1; i < leaveDay; i++) {
                calendar.add(Calendar.DAY_OF_WEEK,1);
                Date day = new Date(calendar.getTime().getTime());
                dateList.add(day);
            }
            for (Date day : dateList) {
                LambdaQueryWrapper<OnDuty> queryWrapper = new LambdaQueryWrapper<>();
                queryWrapper.eq(OnDuty::getDay,day);
                queryWrapper.eq(OnDuty::getEmployeeId,employeeId);
//                queryWrapper.eq(OnDuty::getPhone,phone);
                OnDuty onDutySelect = onDutyMapper.selectOne(queryWrapper);
                if (onDutySelect!=null){
                    onDutySelect.setStatus("出差");
                    onDutyMapper.updateById(onDutySelect);
                }
                OnDuty onDuty = new OnDuty();
                onDuty.setEmployeeId(businessTrip.getEmployeeId());
//                onDuty.setName(businessTrip.getName());
//                onDuty.setPhone(phone);
                onDuty.setDepartmentId(businessTrip.getDepartmentId());
//                onDuty.setDepartment(businessTrip.getDepartment());
//                onDuty.setPosition(businessTrip.getPosition());
                onDuty.setStatus("出差");
                onDuty.setDay(day);
                onDutyMapper.insert(onDuty);
            }
        }
    }

    /***
     * 驳回出差申请
     * @param id 员工id
     * @param adminId 管理员id
     */
    @Override
    public void refuse(Integer id,Integer adminId) {
        BusinessTrip businessTrip = businessTripMapper.selectById(id);
        businessTrip.setStatus("驳回");
        Admin admin = adminMapper.selectById(adminId);
        businessTrip.setApprover(admin.getUsername());
        businessTripMapper.updateById(businessTrip);
    }

    @Override
    public Result appForTrip(BusinessTrip businessTrip) {

        Date leaveTime = businessTrip.getLeaveTime();
        Date backTime = businessTrip.getBackTime();
        Long employeeId = businessTrip.getEmployeeId();

        LambdaQueryWrapper<EmployeeLeave> leaveWrapper = new LambdaQueryWrapper<>();
        leaveWrapper.eq(EmployeeLeave::getEmployeeId,employeeId);
        leaveWrapper.between(EmployeeLeave::getStartTime,leaveTime,backTime)
                .or().between(EmployeeLeave::getEndTime,leaveTime,backTime);
        List<EmployeeLeave> employeeLeaveList = employeeLeaveMapper.selectList(leaveWrapper);
        if (employeeLeaveList.size()>0){
            return new Result(Code.SAVE_ERR,"该时间段您已申请请假！");
        }

        businessTrip.setSubmitTime(new java.util.Date());
        java.util.Date submitTime = businessTrip.getSubmitTime();
        Date date = new Date(submitTime.getTime());
        Integer day = DateUtils.getLeaveDay(date, leaveTime);
        if (day<=1){
            return new Result(Code.SAVE_ERR,"请至少提前1天申请出差！");
        }
        LambdaQueryWrapper<BusinessTrip> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(BusinessTrip::getEmployeeId,employeeId);
//        queryWrapper.eq(BusinessTrip::getPhone,phone);
        queryWrapper.between(BusinessTrip::getLeaveTime,leaveTime,backTime).
                or().between(BusinessTrip::getBackTime,leaveTime,backTime);
        List<BusinessTrip> businessTripList = businessTripMapper.selectList(queryWrapper);
        if (businessTripList.size()>0){
            return new Result(Code.SAVE_ERR,"此时间段内您已申请出差！");
        }
        //出差时间(天数)
        Integer dayGap = DateUtils.getLeaveDay(leaveTime, backTime);
        if (dayGap>=1){
            businessTrip.setStatus("待审核");
            businessTrip.setDay(dayGap);//BigDecimal.valueOf(0)
//            businessTrip.setActualCost();//应该设为null
            businessTripMapper.insert(businessTrip);

            return new Result(Code.SAVE_OK,"申请出差成功！");
        }else {
            return new Result(Code.SAVE_ERR,"申请出差失败，请检查日期！");
        }
    }

    /**
     * 分页+条件 员工获取个人出差记录
     * @param currentPage 当前页
     * @param pageSize 每页最大数
     * @param querySelfAttendanceCondition 搜索条件
     * @return
     */
    @Override
    public IPage<BusinessTrip> getSelfTrip(int currentPage, int pageSize, QuerySelfAttendanceCondition querySelfAttendanceCondition) {

        Date month = querySelfAttendanceCondition.getMonth();//2024-2-1
        IPage<BusinessTrip> iPage=new Page<>(currentPage,pageSize);
        QueryWrapper<BusinessTrip> queryWrapper = new QueryWrapper<>();
        //按状态搜索
        queryWrapper.like(querySelfAttendanceCondition.getStatus()!=null,
                "status", querySelfAttendanceCondition.getStatus());

        LambdaQueryWrapper<Employee> queryWrapper1 = new LambdaQueryWrapper<>();
        queryWrapper1.like(Employee::getPhone, querySelfAttendanceCondition.getPhone());
        List<Employee> employeeList = employeeMapper.selectList(queryWrapper1);

        List<Long> employeeIds = employeeList.stream().map(Employee::getId).collect(Collectors.toList());
        queryWrapper.in("employee_id", employeeIds);//是QueryWrapper的技术语句
        if (month!=null){
            String firstDay = month.toString();//每月的第一天
            String lastDay = DateUtils.getLastDay(firstDay);//每月最后一天

            queryWrapper.between("submit_time",firstDay,lastDay);

            return businessTripMapper.selectPage(iPage,queryWrapper);
        }else {

            return businessTripMapper.selectPage(iPage,queryWrapper);
        }
    }

    /**
     * 员工撤销出差申请
     * @param id 员工申请id
     */
    @Override
    public void cancelTrip(Integer id) {
        businessTripMapper.deleteById(id);
    }

    /**
     * 员工上报此次出差实际花费
     * @param id 出差记录ID
     */
    @Override
    public void setActualCost(Integer id,BigDecimal actualCost) {
        BusinessTrip businessTrip = businessTripMapper.selectById(id);
        if (businessTrip!=null){
            businessTrip.setActualCost(actualCost);
//            businessTrip.setStatus("待审核");
//            System.out.println("actualCost->>"+businessTrip.getActualCost());
            businessTripMapper.updateById(businessTrip);
        }else {
            throw new BusinessException(Code.SELECT_ERR,"查无此人");
        }
    }


    //员工查询此次出差实际花费是否上报
    @Override
    public Result getActualCost(Integer id) {

        BusinessTrip businessTrip = businessTripMapper.selectById(id);
        System.out.println("businessTrip是什么"+businessTrip);
        if(businessTrip.getActualCost()!=null){
            if (businessTrip.getActualCost().compareTo(BigDecimal.ZERO) > 0){
                return new Result(Code.SELECT_ERR,"此次出差已上报实际花费！");
            }else {
                return new Result(Code.SELECT_OK,"此次出差暂未上报实际花费！");
            }
        }
        return new Result(Code.SELECT_OK,"没有查到出差申请记录！");
    }


    //管理员候补出差记录
    @Override
    public void addBusinessTrip(Integer adminId, BusinessTrip businessTrip) {
        Admin admin = adminMapper.selectById(adminId);
        businessTrip.setApprover(admin.getUsername());
        businessTrip.setStatus("同意");
        Date startTime = businessTrip.getLeaveTime();
        Date endTime = businessTrip.getBackTime();
        Integer leaveDay = DateUtils.getLeaveDay(startTime, endTime);
        businessTrip.setDay(leaveDay);
        businessTrip.setSubmitTime(new java.util.Date());
        businessTripMapper.insert(businessTrip);
        Long employeeId = businessTrip.getEmployeeId();
        Calendar calendar =Calendar.getInstance();
        calendar.setTime(startTime);
        List<Date> dateList = new ArrayList<>();
        dateList.add(startTime);

        for (int i = 1; i < leaveDay; i++) {
            calendar.add(Calendar.DAY_OF_WEEK,1);
            Date day = new Date(calendar.getTime().getTime());
            dateList.add(day);
        }
        for (Date day : dateList) {
            LambdaQueryWrapper<OnDuty> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(OnDuty::getDay, day);
            queryWrapper.eq(OnDuty::getEmployeeId,employeeId);
//            queryWrapper.eq(OnDuty::getPhone,phone);
            OnDuty onDutySelect = onDutyMapper.selectOne(queryWrapper);
            if (onDutySelect != null) {
                onDutySelect.setStatus("出差");
                onDutyMapper.updateById(onDutySelect);
            }else {
                OnDuty onDuty = new OnDuty();
                onDuty.setEmployeeId(businessTrip.getEmployeeId());
//                onDuty.setName(businessTrip.getName());
                onDuty.setDepartmentId(businessTrip.getDepartmentId());
//                onDuty.setDepartment(businessTrip.getDepartment());
//                onDuty.setPosition(businessTrip.getPosition());
//                onDuty.setPhone(phone);
                onDuty.setDay(day);
                onDuty.setStatus("出差");
                onDutyMapper.insert(onDuty);
            }
        }
    }

}
